package com.zb.service.imp.middleware;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.zb.dao.ext.charger.OmsChargerBespeakBillRecordDao;
import com.zb.dao.ext.charger.OmsChargerChargeBillRecordDao;
import com.zb.dao.ext.charger.OmsChargerDao;
import com.zb.dao.ext.charger.OmsChargerOfflineWhitelistDao;
import com.zb.dao.ext.charger.OmsChargerRateDao;
import com.zb.dao.ext.charger.OmsChargerStateAlternateDao;
import com.zb.dao.ext.charger.OmsChargerStateDirectDao;
import com.zb.dao.ext.common.OmsSplitratioSchemeDao;
import com.zb.entity.base.JsonCommon;
import com.zb.entity.base.JsonForList;
import com.zb.entity.base.OmsServiceSplitratio;
import com.zb.entity.base.OmsSplitratioScheme;
import com.zb.entity.charger.*;
import com.zb.entity.exception.BizException;
import com.zb.service.charger.OmsChargerErrorRecordService;
import com.zb.service.imp.middleware.vo.ChargerReplyMsgHeader;
import com.zb.service.imp.sys.PaymentDetail;
import com.zb.service.middleware.MessageService;
import com.zb.service.middleware.OmsBespeakService;
import com.zb.tcp.rpc.as.SystemAppServerRpcClient;
import com.zb.tcp.rpc.as.client.constant.AppServerConstant;
import com.zb.tcp.rpc.as.client.entity.AppOrderNotifyParam;
import com.zb.tcp.rpc.as.client.entity.AppReservationNotifyParam;
import com.zb.tcp.rpc.os.OrderRpcClient;
import com.zb.tcp.socket.exception.CreateConnectionFailException;
import com.zb.tcp.socket.exception.DuplicateInstructionException;
import com.zb.tcp.socket.exception.RetryFailException;
import com.zb.util.CardUtils;
import com.zb.util.OmsConstant;
import com.zb.util.OrderConstant;
import com.zb.util.RedisClient;
import com.zb.util.StringUtil;
import com.zb.util.serialGenerater;
import com.zb.util.OmsConstant.MsgCodeEnum;
import com.zb.util.OrderConstant.BizSystemCode;
import com.zb.util.OrderConstant.OrderServiceEnum;
import com.zb.vo.os.OrderBaseData;
import com.zb.vo.os.RetVO;
import com.zb.vo.os.RetVO.OrdersStatus;

@Service @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class OmsBespeakServiceImpl implements OmsBespeakService {
	private Log log = LogFactory.getLog(OmsBespeakServiceImpl.class);

	public static final int DEFAULT_BESPEAK_MINITUE = 360;

	// @SuppressWarnings("rawtypes")
	// @Autowired
	// BaseDao baseDao;
	@Resource
	OmsChargerDao omsChargerDao;
	@Resource
	OmsChargerStateDirectDao omsChargerStateDirectDao;
	@Resource
	OmsChargerStateAlternateDao omsChargerStateAlternateDao;
	@Resource
	OmsChargerBespeakBillRecordDao omsChargerBespeakBillRecordDao;
	@Resource
	OmsChargerOfflineWhitelistDao omsChargerOfflineWhitelistDao;
	@Resource
	OmsChargerRateDao omsChargerRateDao;
	@Resource(name = "ev3cMessageServiceImpl")
	MessageService ev3cMessageService;
	@Resource(name = "ev3c2MessageServiceImpl")
	MessageService ev3c2MessageService;
//	@Resource
//	OrderRpcClient orderRpcClient;
	@Resource
	OmsSplitratioSchemeDao omsSplitratioSchemeDao;
//	@Resource
//	SystemAppServerRpcClient systemAppServerRpcClient;
	@Resource
	OmsChargerErrorRecordService omsChargerErrorRecordService;
	@Resource
	OmsChargerChargeBillRecordDao omsChargerChargeBillRecordDao;

	@Resource(name = "ev3c2MessageWrapperImpl")
	MessageWrapper messageWapper;

	@Resource
	PriceService priceService;
	String ev3c_frameCode, ev3c_msgHeader, ev3c_msgBody, protocol_type = "", protocol_version = "";
	JsonCommon<String> json = new JsonCommon<String>();

	private static Lock lock = new ReentrantLock(); // 锁对象

	@Override
	public void bespeakReturn(Map<String, String> map) {
		protocol_type = map.get("protocol_type");
		protocol_version = map.get("protocol_version");
		switch (protocol_type) {
		case "1":
			ev3c_frameCode = "14";
			switch (protocol_version) {
			case "0101":
				ev3c0101BespeakReturn(map);
				break;
			case "0102":
				// 信息头
				ev3c0102BespeakReturn(map);
				// 有信息体
				break;
//			case "0103":
//				// 有信息头，无信息体
//				json = ev3c0103BespeakReturn(map);
//				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}

	/**
	 * 针对0101或0102 版本协议
	 * 预约回复执行流程如下:
	 * 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);否则进入第二步。
	 * 2.如果响应码为000000,根据实际情况判断是否需要更新直流或交流表信息
     * 3.更新预约记录表(状态为已预约)
     * 4.根据卡号判断,如果为APP卡号,则调用App  ReservationNotifyParam通知;如果为企业卡号,则调用企业回调URL:参考主服务器login(用户登录使用)接口。
	 * 先查询oms_oper_list中的notifyUrl,如果没有,就不管了。
	 * ps:企业用户登录流程:先访问主服务器,成功后把相应的信息存入oms_oper_list表中。
	 *
	 * 预约记录表:预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
	 * @param map
	 * @return JsonCommon<String>
	 */
	private void ev3c0101BespeakReturn(Map<String, String> map) {
		log.info("Receive response message from bespeakReturn! curTime = " + new Date().getTime());
		log.info(map);
		JsonCommon<String> json = new JsonCommon<String>();
		String chargerId, responseMsgHeader, responseMsgBody;
		chargerId = map.get("chargerId");
		String data = map.get("data");
		String port = map.get("port"); // 充电口号 BIN码 1 00表示A口,01表示B口   10表示C口···目前还没有C口
		String userCard = map.get("userCard"); // 用户卡号
		String responseCode= data.substring(8, 14); // 获取响应码

		responseMsgBody = "";
		responseMsgHeader = data.substring(0, 2)+"0000"+ data.substring(6, 34) + "57" + data.substring(36,50);
		json.setPojo(responseMsgHeader + responseMsgBody);

		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(port, 2); // 数据库中是从0开始,报文是从0开始
		charger_query.setPort_no(port_no);
		OmsCharger charger = (OmsCharger) omsChargerDao.findOneExample(charger_query, null, null);
		// 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);否则进入第二步。
		if (checkChargerReplyMessageStatus(responseCode)) { // 正常
			log.info("Receive response message from bespeakReturn(responseCode is normal)");
			// 2.处理预约,更新预约记录表(状态为已预约)
			OmsChargerBespeakBillRecord bespeakBillRecord_query = new OmsChargerBespeakBillRecord();
			bespeakBillRecord_query.setCharger_id(chargerId);
			bespeakBillRecord_query.setUser_pay_card(userCard);
			bespeakBillRecord_query.setPort_no(port_no);
			bespeakBillRecord_query.setStatus(1);
			OmsChargerBespeakBillRecord bespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExample(bespeakBillRecord_query,"start_time","desc");
			bespeakBillRecord.setStatus(2); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
//			String oms_msg_bespeak_end_jrnl = serialGenerater.generateSerialNo();
//			bespeakBillRecord.setOms_msg_bespeak_end_jrnl(oms_msg_bespeak_end_jrnl); // 报文结束预约流水号,系统生成,格式为:YYYY-MM-DD-HH-MI-SS加上四位序号,例如:0x20 0x15 0x05 0x
			omsChargerBespeakBillRecordDao.updateObject(bespeakBillRecord); // 更新状态

			int chargerType = 1; // 1:直流  2:交流  3:混合
			OmsChargerStateDirect directState = null; // 直流表信息
			OmsChargerStateAlternate alternateState = null; // 交流表信息
			if (charger.getCharger_type() != null) {
				chargerType = charger.getCharger_type();
				switch (chargerType) { // 1:直流  2:交流  3:混合
				case 1:
					OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
					directState_query.setPort_no(port_no);
					directState_query.setCharger_id(map.get("chargerId"));
					directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);

					directState.setCharge_status(1); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
					directState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
					directState.setBespeak_jrnl(bespeakBillRecord.getOms_msg_bespeak_jrnl()); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
					directState.setUser_pay_card(userCard);
					omsChargerStateDirectDao.updateObject(directState);
					break;
				case 2:
					OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
					alternateState_query.setPort_no(port_no);
					alternateState_query.setCharger_id(chargerId);
					alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);

					alternateState.setCharge_status(1); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
					alternateState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
					alternateState.setBespeak_jrnl(bespeakBillRecord.getOms_msg_bespeak_jrnl()); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
					alternateState.setUser_pay_card(userCard);
					omsChargerStateAlternateDao.updateObject(alternateState);
					break;
				default:
					break;
				}
			}

			// 3.根据卡号判断,如果为APP卡号,则调用App ReservationNotifyParam通知;
			// 如果为企业卡号,则调用企业回调URL:参考主服务器login(用户登录使用)接口。
			// 先查询oms_oper_list中的notifyUrl,如果没有,就不管了。
			// 企业用户登录流程:先访问主服务器,成功后把相应的信息存入oms_oper_list表中。
			// 线上卡是18808开头(08 线上卡),线下卡是18806开头(06 现金卡),05 身份认证卡
			try
			{
				notifyOnReservationSuccess(AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_RESERVATION, bespeakBillRecord, charger);
			}
			catch (BizException e)
			{
				log.error(e.getMessage(), e);
			}

		} else { // 入库oms_charger_error_record[故障记录表]
//			log.info("Receive response message from bespeakReturn(OmsChargerErrorRecord)");
//			OmsChargerErrorRecord record = new OmsChargerErrorRecord();
//			record.setCharger_id(chargerId);
//			record.setError_code(responseCode);
//			record.setError_msg("BespeakReturn fault!");
//			record.setStatus(0); // 0:未处理,1:已处理
//			record.setValid_flag(1);
//			record.setCreate_oper_id("000");
//			record.setCreate_time(new Date());
//			omsChargerErrorRecordService.add(record);
//
//			// 报文中需要有直流和交流的区别,如果是为了中新用的,就应该是oms_charger_state_direct[直流充电桩状态表]
//			if (charger.getCharger_type() != null) {
//				int chargerType = charger.getCharger_type();
//				switch (chargerType) { // 1:直流  2:交流  3:混合
//				case 1:
//					OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
//					directState_query.setPort_no(port_no);
//					directState_query.setCharger_id(map.get("chargerId"));
//					OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
//					directState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
//					directState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
//					directState.setBespeak_jrnl(""); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
//					omsChargerStateDirectDao.updateObject(directState);
//					break;
//				case 2:
//					OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
//					alternateState_query.setPort_no(port_no);
//					alternateState_query.setCharger_id(chargerId);
//					OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
//					alternateState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
//					alternateState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
//					alternateState.setBespeak_jrnl(""); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
//					omsChargerStateAlternateDao.updateObject(alternateState);
//					break;
//				default:
//					break;
//				}
//			}
//
//			json.setCode(OmsConstant.ErrorCodeEnum.ConnectionResultChargerException.value());
//			json.setMsg("chargerId " + chargerId + "userCard " + userCard + " ev3c0101BespeakReturn: bespeakReturn connection status fail!"); // 带卡号
//			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101BespeakReturn -> result:bespeakReturn connection status fail!");
		}
	}

	private void ev3c0102BespeakReturn(Map<String, String> map) {
		ev3c0101BespeakReturn(map);
	}

	private JsonCommon<String> ev3c0103BespeakReturn(Map<String, String> map) {
		JsonCommon<String> json = new JsonCommon<String>();
		String chargerId, requestURL, responseMsgHeader, responseMsgBody;
		// String[] header = StringUtil.getMessageHeader(data);
		// Map<String,String> headMap = StringUtil.getParameter(request);
		chargerId = map.get("chargerId");
		String data = map.get("data");
		String port = map.get("port"); // 充电口号 BIN码 1 00表示A口，01表示B口
												// 10表示C口···目前还没有C口
		String userCard = map.get("userCard"); // 用户卡号
		String startTime = map.get("startTime"); // 预约开始时间 BCD码 7
													// 格式YYYY-MM-DD-hh-mm-ss
													// 例如：0x20 0x15 0x05 0x10
													// 0x13 0x20
													// 0x11,表示2015年5月10日13时20分11秒
		Date startTime_date = StringUtil.StrToDate(startTime);
		// 之前是char_bespeak_record，现在这个表已经被合并到char_bespeak_bill_record[预约费用记录表]中了。
		OmsChargerBespeakBillRecord billRecord = new OmsChargerBespeakBillRecord();
		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(port, 2);// 数据库中是从0开始，报文是从0开始
//		charger_query.setPort_no(port_no);
		OmsCharger charger = (OmsCharger) omsChargerDao.findOneExample(charger_query, null, null);

//		String key = chargerId+port_no+userCard;
		String key = chargerId+port+userCard+"_bespeakMinute";
		String bespeakMinute =  RedisClient.get(key);
		if(StringUtil.isNotBlank(bespeakMinute)){
			int bespeakMinute_int = Integer.valueOf(bespeakMinute);
//			startTime_date.
			Calendar ca = Calendar.getInstance();
			ca.setTime(startTime_date);
			ca.add(Calendar.MINUTE, bespeakMinute_int);
			Date estimate_end_time=ca.getTime();
//			Date estimate_end_time = startTime_date + bespeakMinute_int;
			billRecord.setEstimate_end_time(estimate_end_time);
			RedisClient.delByKey(key);
		}
		billRecord.setCharger_id(map.get("chargerId").toString());
		billRecord.setPort_no(port_no);
		billRecord.setUser_pay_card(userCard);
		billRecord.setStation_id(charger.getStation_id());
		billRecord.setValid_flag(1);
		billRecord.setStart_time(startTime_date);//1.3独有
		billRecord.setIs_done(0);
		billRecord.setEstimate_end_time(null);// 预约理论结束时间
		billRecord.setBespeak_deal_charge(null);// 最终预约结算费用
		billRecord.setBespeak_jrnl(userCard+"0"+port_no+StringUtil.now14time()+serialGenerater.generateSerialNo());
		omsChargerBespeakBillRecordDao.save(billRecord);
		// 更新状态 oms_charger_state_alternate[交流充电桩状态表]
		// oms_charger_state_direct[直流充电桩状态表]
		// 报文中需要有直流和交流的区别，如果是为了中新用的，就应该是oms_charger_state_direct[直流充电桩状态表]
		if (charger.getCharger_type() != null) {
			int chargerType = charger.getCharger_type();
			switch (chargerType) {// 1--直流 2--交流 3--混合
			case 1:
				OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
				directState_query.setPort_no(port_no);
				directState_query.setCharger_id(map.get("chargerId"));
				OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao
						.findOneExample(directState_query, null, null);
				directState.setCharge_status(1);
				directState.setOnline_status(1);
				omsChargerStateDirectDao.updateObject(directState);
				break;
			case 2:
				OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
				alternateState_query.setPort_no(port_no);
				alternateState_query.setCharger_id(chargerId);
				OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao
						.findOneExample(alternateState_query, null, null);
				alternateState.setCharge_status(1);
				alternateState.setOnline_status(1);
				omsChargerStateAlternateDao.updateObject(alternateState);
				break;
			default:
				break;
			}
		}
		json.setCode("200");
		json.setMsg("ok");
//		json.setPojo(responseMsgHeader + responseMsgBody);
		return json;
	}

	@Override
	public void cancelBespeakReturn(Map<String, String> map) throws RetryFailException, CreateConnectionFailException
	{
		protocol_type = map.get("protocol_type");
		protocol_version = map.get("protocol_version");
		String data = map.get("data");
		switch (protocol_type) {
		case "1":
			ev3c_frameCode = "14";
			switch (protocol_version) {
			case "0101":
				ev3c0101CancelBespeakReturn(map, data);
				break;
			case "0102":
				ev3c0102CancelBespeakReturn(map, data);
				break;
//			case "0103":
//				json = ev3c0103CancelBespeakReturn(map, data);
//				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	}

	/**
	 * 针对0101或0102 版本协议
	 * 取消预约执行流程如下:
	 * 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);
	 * 2.生成订单,通知app或第三方App OrderNotifyParam通知
	 * 3.通知app或第三方App ReservationNotifyParam通知
	 *
	 * @param map
	 * @param data
	 * @return
	 */
//	private void ev3c0101CancelBespeakReturn(Map<String, String> map, String data) throws RetryFailException, CreateConnectionFailException
//	{
//		log.info("Receive response message from cancelBespeakReturn! curTime = " + new Date().getTime());
//		ev3c_frameCode = "58";
//		JsonCommon<String> json = new JsonCommon<String>();
//		map.put("portNo", data.substring(50,52)); // 截取枪口号
//		String chargerId, responseMsgHeader, responseMsgBody;
//		chargerId = map.get("chargerId");
//		String port = map.get("port"); // 充电口号 BIN码 1 00表示A口,01表示B口,10表示C口···目前还没有C口
//		String userCard = map.get("userCard"); // 用户卡号
//		String responseCode= data.substring(8, 14); // 获取响应码
//		OmsCharger charger_query = new OmsCharger();
//		charger_query.setCharger_id(chargerId);
//		int port_no = Integer.parseInt(port, 2);// 数据库中是从0开始，报文是从0开始
//		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
//		responseMsgBody = "";
//		responseMsgHeader = data.substring(0, 2)+"0000"+data.substring(6, 34) + "58" + data.substring(36,50);
//		try {
//			// 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);否则进入第二步。
//			if (checkChargerReplyMessageStatus(responseCode)) { // 正常
//				log.info("Receive response message from cancelbespeakReturn(responseCode is normal)");
//				// 2.生成订单,通知app或第三方App OrderNotifyParam通知
//				OmsChargerBespeakBillRecord omsChargerBespeakBillRecord_query = new OmsChargerBespeakBillRecord();
//				omsChargerBespeakBillRecord_query.setCharger_id(chargerId);
//				omsChargerBespeakBillRecord_query.setPort_no(port_no);
//				omsChargerBespeakBillRecord_query.setUser_pay_card(userCard);
//				OmsChargerBespeakBillRecord omsChargerBespeakBillRecord;
//				//TODO 2:已预约  3:取消预约中 加条件 ，如果没有就不调用订单，直接报文返回
//				omsChargerBespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExampleByCondition(omsChargerBespeakBillRecord_query, " where charger_id = '" + chargerId + "' and port_no = " + port_no + " and user_pay_card = '"+ userCard +"'  order by start_time desc ");
//
//				Date now = new Date();
//				BigDecimal totalAmount = priceService.computeFee(charger.getRate_schema_bespeak_fee(), omsChargerBespeakBillRecord.getStart_time(), now);
//				omsChargerBespeakBillRecord.setBespeak_deal_before(Float.valueOf(totalAmount.toString()));
//				omsChargerBespeakBillRecord.setActual_end_time(now);
//				RetVO.CreatedOrderVO retVO = createOrderWhenCancelReservation(omsChargerBespeakBillRecord, charger);
//				// json = sendOrderToAppServer(map, 2);
//				// 3.通知app或第三方App ReservationNotifyParam通知
//				omsChargerBespeakBillRecord.setStatus(4); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
//				omsChargerBespeakBillRecord.setOrder_no(retVO.getOrderNo());
//				omsChargerBespeakBillRecord.setBespeak_deal_charge(Float.valueOf(retVO.getTotalFee().toString()));
//				omsChargerBespeakBillRecordDao.updateObject(omsChargerBespeakBillRecord); // 更新状态
//
//				// 4.处理取消预约后,改变桩对应枪口的状态
//				// 报文中需要有直流和交流的区别,如果是为了中新用的,就应该是oms_charger_state_direct[直流充电桩状态表]
//				if (charger.getCharger_type() != null) {
//					int chargerType = charger.getCharger_type();
//					switch (chargerType) { // 1:直流  2:交流  3:混合
//					case 1:
//						OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
//						directState_query.setPort_no(port_no);
//						directState_query.setCharger_id(map.get("chargerId"));
//						OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
//						directState.setCharge_status(0); // 设置为空闲
//						omsChargerStateDirectDao.updateObject(directState);
//						break;
//					case 2:
//						OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
//						alternateState_query.setPort_no(port_no);
//						alternateState_query.setCharger_id(chargerId);
//						OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
//						alternateState.setCharge_status(0); // 设置为空闲
//						omsChargerStateAlternateDao.updateObject(alternateState);
//						break;
//					default:
//						break;
//					}
//				}
//
//				// 5.通知:取消预约通知接口
//				log.info("Receive response message from cancelBespeakReturn(AppReservationNotifyParam)");
//				try {
//					notifyOnReservationSuccess(AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_CANCEL_RESERVATION, omsChargerBespeakBillRecord, charger);
//					notifyOnReservationFee(retVO, omsChargerBespeakBillRecord);
//				} catch (BizException e) {
//					log.error(e.getMessage(), e);
//					json.setPojo(responseMsgHeader + responseMsgBody);
//					json.setCode("400");
//					throw e;
//				}
//
//				// 4.发送报文
//				try {
//					ev3cMessageService.sendNoWait(responseMsgHeader+responseMsgBody, chargerId);
//
//					log.debug("chargerId "+ chargerId +" cancelBespeakReturn reservationNotify success, cancelBespeakReturn sendNoWait success!");
//					json.setPojo(responseMsgHeader + responseMsgBody);
//					json.setCode("200");
//				} catch (CreateConnectionFailException | RetryFailException e) {
//					log.error(e.getMessage(), e);
//					json.setPojo(responseMsgHeader + responseMsgBody);
//					json.setCode("400");
//					throw e;
//				}
//			} else { // 入库oms_charger_error_record[故障记录表]
////				OmsChargerErrorRecord record = new OmsChargerErrorRecord();
////				record.setCharger_id(chargerId);
////				record.setError_code(responseCode);
////				record.setError_msg("CancelBespeakReturn fault!");
////				record.setStatus(0); // 0:未处理,1:已处理
////				record.setValid_flag(1);
////				record.setCreate_oper_id("000");
////				record.setCreate_time(new Date());
////				omsChargerErrorRecordService.add(record);
////
////				// 报文中需要有直流和交流的区别,如果是为了中新用的,就应该是oms_charger_state_direct[直流充电桩状态表]
////				if (charger.getCharger_type() != null) {
////					int chargerType = charger.getCharger_type();
////					switch (chargerType) { // 1:直流  2:交流  3:混合
////					case 1:
////						OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
////						directState_query.setPort_no(port_no);
////						directState_query.setCharger_id(map.get("chargerId"));
////						OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
////						directState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
////						directState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
////						omsChargerStateDirectDao.updateObject(directState);
////						break;
////					case 2:
////						OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
////						alternateState_query.setPort_no(port_no);
////						alternateState_query.setCharger_id(chargerId);
////						OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
////						alternateState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
////						alternateState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
////						omsChargerStateAlternateDao.updateObject(alternateState);
////						break;
////					default:
////						break;
////					}
////				}
//			}
//		} catch (Exception e) {
//			log.error(e.getMessage(), e);
//			json.setPojo(responseMsgHeader + responseMsgBody);
//			json.setCode("400");
//		}
//	}

	/**
	 * pengyu 20160923 modify for test
	 * 针对0101或0102 版本协议
	 * 取消预约执行流程如下:
	 * 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);
	 * 2.生成订单,通知app或第三方App OrderNotifyParam通知
	 * 3.通知app或第三方App ReservationNotifyParam通知
	 *
	 * @param map
	 * @param data
	 * @return
	 */
	private void ev3c0101CancelBespeakReturn(Map<String, String> map, String data) throws RetryFailException, CreateConnectionFailException
	{
		log.info("Receive response message from cancelBespeakReturn! curTime = " + new Date().getTime());
		ev3c_frameCode = "58";
		JsonCommon<String> json = new JsonCommon<String>();
		map.put("portNo", data.substring(50,52)); // 截取枪口号
		String chargerId, responseMsgHeader, responseMsgBody;
		chargerId = map.get("chargerId");
		String port = map.get("port"); // 充电口号 BIN码 1 00表示A口,01表示B口,10表示C口···目前还没有C口
		String userCard = map.get("userCard"); // 用户卡号
		String responseCode= data.substring(8, 14); // 获取响应码
		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(port, 2);// 数据库中是从0开始，报文是从0开始
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		responseMsgBody = "";
		responseMsgHeader = data.substring(0, 2)+"0000"+data.substring(6, 34) + "58" + data.substring(36,50);
		try {
			// 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);否则进入第二步。
			if (checkChargerReplyMessageStatus(responseCode)) { // 正常
				log.info("Receive response message from cancelbespeakReturn(responseCode is normal)");
				// 2.生成订单,通知app或第三方App OrderNotifyParam通知
				OmsChargerBespeakBillRecord omsChargerBespeakBillRecord_query = new OmsChargerBespeakBillRecord();
				omsChargerBespeakBillRecord_query.setCharger_id(chargerId);
				omsChargerBespeakBillRecord_query.setPort_no(port_no);
				omsChargerBespeakBillRecord_query.setUser_pay_card(userCard);
				OmsChargerBespeakBillRecord omsChargerBespeakBillRecord;
				//TODO 2:已预约  3:取消预约中 加条件 ，如果没有就不调用订单，直接报文返回
				omsChargerBespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExampleByCondition(omsChargerBespeakBillRecord_query, " where charger_id = '" + chargerId + "' and port_no = " + port_no + " and user_pay_card = '"+ userCard +"' and status in (2,3)  order by start_time desc ");

				if(omsChargerBespeakBillRecord==null){
					// 4.发送报文
					try {
						responseMsgHeader = data.substring(0, 2)+"000001"+"FF0201"+data.substring(14, 34) + "58" + data.substring(36,50);
						ev3cMessageService.sendNoWait(responseMsgHeader+responseMsgBody, chargerId);

						log.debug("chargerId "+ chargerId +" cancelBespeakReturn reservationNotify success, cancelBespeakReturn sendNoWait success!");
						json.setPojo(responseMsgHeader + responseMsgBody);
						json.setCode("200");
						return;
					} catch (CreateConnectionFailException | RetryFailException e) {
						log.error(e.getMessage(), e);
						json.setPojo(responseMsgHeader + responseMsgBody);
						json.setCode("400");
						throw e;
					}
				}
				Date now = new Date();
				List<PaymentDetail> reservationFeeDetails = new ArrayList<>();
				BigDecimal totalAmount = priceService.computeFee(charger.getRate_schema_bespeak_fee(), omsChargerBespeakBillRecord.getStart_time(), now, reservationFeeDetails);
				omsChargerBespeakBillRecord.setBespeak_deal_before(Float.valueOf(totalAmount.toString()));
				omsChargerBespeakBillRecord.setActual_end_time(now);
				RetVO.CreatedOrderVO retVO = createOrderWhenCancelReservation(omsChargerBespeakBillRecord, charger, reservationFeeDetails);
				// json = sendOrderToAppServer(map, 2);
				// 3.通知app或第三方App ReservationNotifyParam通知
				omsChargerBespeakBillRecord.setStatus(4); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
				omsChargerBespeakBillRecord.setOrder_no(retVO.getOrderNo());
				omsChargerBespeakBillRecord.setBespeak_deal_charge(Float.valueOf(retVO.getTotalFee().toString()));
				omsChargerBespeakBillRecordDao.updateObject(omsChargerBespeakBillRecord); // 更新状态

				// 4.处理取消预约后,改变桩对应枪口的状态
				// 报文中需要有直流和交流的区别,如果是为了中新用的,就应该是oms_charger_state_direct[直流充电桩状态表]
				if (charger.getCharger_type() != null) {
					int chargerType = charger.getCharger_type();
					switch (chargerType) { // 1:直流  2:交流  3:混合
					case 1:
						OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
						directState_query.setPort_no(port_no);
						directState_query.setCharger_id(map.get("chargerId"));
						OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
						directState.setCharge_status(0); // 设置为空闲
						omsChargerStateDirectDao.updateObject(directState);
						break;
					case 2:
						OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
						alternateState_query.setPort_no(port_no);
						alternateState_query.setCharger_id(chargerId);
						OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
						alternateState.setCharge_status(0); // 设置为空闲
						omsChargerStateAlternateDao.updateObject(alternateState);
						break;
					default:
						break;
					}
				}

				// 5.通知:取消预约通知接口
				log.info("Receive response message from cancelBespeakReturn(AppReservationNotifyParam)");
				try {
					notifyOnReservationSuccess(AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_CANCEL_RESERVATION, omsChargerBespeakBillRecord, charger);
					notifyOnReservationFee(retVO, omsChargerBespeakBillRecord);
				} catch (BizException e) {
					log.error(e.getMessage(), e);
					json.setPojo(responseMsgHeader + responseMsgBody);
					json.setCode("400");
					throw e;
				}

				// 4.发送报文
				try {
					ev3cMessageService.sendNoWait(responseMsgHeader+responseMsgBody, chargerId);

					log.debug("chargerId "+ chargerId +" cancelBespeakReturn reservationNotify success, cancelBespeakReturn sendNoWait success!");
					json.setPojo(responseMsgHeader + responseMsgBody);
					json.setCode("200");
				} catch (CreateConnectionFailException | RetryFailException e) {
					log.error(e.getMessage(), e);
					json.setPojo(responseMsgHeader + responseMsgBody);
					json.setCode("400");
					throw e;
				}
			} else { // 入库oms_charger_error_record[故障记录表]
//				OmsChargerErrorRecord record = new OmsChargerErrorRecord();
//				record.setCharger_id(chargerId);
//				record.setError_code(responseCode);
//				record.setError_msg("CancelBespeakReturn fault!");
//				record.setStatus(0); // 0:未处理,1:已处理
//				record.setValid_flag(1);
//				record.setCreate_oper_id("000");
//				record.setCreate_time(new Date());
//				omsChargerErrorRecordService.add(record);
//
//				// 报文中需要有直流和交流的区别,如果是为了中新用的,就应该是oms_charger_state_direct[直流充电桩状态表]
//				if (charger.getCharger_type() != null) {
//					int chargerType = charger.getCharger_type();
//					switch (chargerType) { // 1:直流  2:交流  3:混合
//					case 1:
//						OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
//						directState_query.setPort_no(port_no);
//						directState_query.setCharger_id(map.get("chargerId"));
//						OmsChargerStateDirect directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
//						directState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
//						directState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
//						omsChargerStateDirectDao.updateObject(directState);
//						break;
//					case 2:
//						OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
//						alternateState_query.setPort_no(port_no);
//						alternateState_query.setCharger_id(chargerId);
//						OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
//						alternateState.setCharge_status(3); // 设置电桩状态为(0:空闲,1:预约,2:充电,3:故障,4:占用中(针对双枪单充等情况),5:刷卡中,8:离线)
//						alternateState.setOnline_status(1); // 在线状态(0:代表离线,1:代表在线)
//						omsChargerStateAlternateDao.updateObject(alternateState);
//						break;
//					default:
//						break;
//					}
//				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			json.setPojo(responseMsgHeader + responseMsgBody);
			json.setCode("400");
		}
	}



	private void ev3c0102CancelBespeakReturn(Map<String, String> map, String data) throws RetryFailException, CreateConnectionFailException
	{
		ev3c0101CancelBespeakReturn(map, data);
	}

	private JsonCommon<String> ev3c0103CancelBespeakReturn(Map<String, String> map, String data) {
//		String endTime = data.substring(86, 100); // 预约结束时间 BCD码 7
//		// 格式YYYY-MM-DD-hh-mm-ss
//		// 例如：0x20 0x15 0x05 0x10
//		// 0x13 0x20
//		// 0x11,表示2015年5月10日13时20分11秒
//		Date endTime_date = StringUtil.StrToDate(endTime);
		JsonCommon<String> json = new JsonCommon<String>();
		String chargerId, requestURL, responseMsgHeader, responseMsgBody;
		// String[] header = StringUtil.getMessageHeader(data);
		// Map<String,String> headMap = StringUtil.getParameter(request);
		chargerId = map.get("chargerId");
		// String userCard = "0";
		String port = map.get("port"); // 充电口号 BIN码 1 00表示A口，01表示B口
												// 10表示C口···目前还没有C口
		String userCard = map.get("userCard"); // 用户卡号
		String startTime = map.get("startTime"); // 预约开始时间 BCD码 7  1.3独有
		Date startTime_date = StringUtil.StrToDate(startTime);
		String endTime = map.get("endTime"); // 
		Date endTime_date = StringUtil.StrToDate(endTime);
		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(port, 2);// 数据库中是从0开始，报文是从0开始
//		charger_query.setPort_no(port_no);
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		if (charger == null || charger.getCharger_type() == null) {
			json.setCode("400");
			json.setMsg("no charger found");
			responseMsgHeader =data.substring(0, 8)+OmsConstant.MsgResponseCodeEnum.SysError.value()+data.substring(14, 34)+ev3c_frameCode+data.substring(36,50);
			json.setPojo(responseMsgHeader);
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0103CancelBespeakReturn -> result:no charger found!");
			return json;
		}

		// omsChargerBespeakBillRecordDao.updateObject();
		int chargerType = charger.getCharger_type();
		switch (chargerType) {// 1--直流 2--交流 3--混合
		case 1:
			OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
			directState_query.setPort_no(port_no);
			directState_query.setCharger_id(chargerId);
			OmsChargerStateDirect directState = omsChargerStateDirectDao.findOneExample(directState_query, null, null);
			directState.setCharge_status(0);
			directState.setOnline_status(1);
			omsChargerStateDirectDao.updateObject(directState);
			break;
		case 2:
			OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
			alternateState_query.setPort_no(port_no);
			alternateState_query.setCharger_id(chargerId);
			OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query,
					null, null);
			alternateState.setCharge_status(0);
			alternateState.setOnline_status(1);
			omsChargerStateAlternateDao.updateObject(alternateState);
			break;
		default:
			break;
		}
		OmsChargerBespeakBillRecord omsChargerBespeakBillRecord_query = new OmsChargerBespeakBillRecord();
		omsChargerBespeakBillRecord_query.setCharger_id(chargerId);
		omsChargerBespeakBillRecord_query.setPort_no(port_no);
		omsChargerBespeakBillRecord_query.setUser_pay_card(userCard);
		omsChargerBespeakBillRecord_query.setStart_time(startTime_date);
		Date now  = new Date();
//		omsChargerBespeakBillRecord.setStart_time(start_time);//ev3c 1.1 1.2 是没有预约时间和实际预约结束时间 返回的
		OmsChargerBespeakBillRecord omsChargerBespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExampleByCondition(omsChargerBespeakBillRecord_query, " order by start_time desc ");
		boolean flag = true;
		if(omsChargerBespeakBillRecord == null){
			flag = false;
			omsChargerBespeakBillRecord = new OmsChargerBespeakBillRecord();
			omsChargerBespeakBillRecord.setValid_flag(1);
			omsChargerBespeakBillRecord.setBespeak_jrnl(userCard+"0"+port_no+StringUtil.now14time());
		}
		// 调用OS接口生成订单，更新bespeak_deal_charge  最终预约结算费用
		List<OrderBaseData> orderBaseDatas = new ArrayList<OrderBaseData>();
		OrderBaseData orderBaseData = new OrderBaseData();
		if(userCard.startsWith("18808")&&!userCard.substring(0, 9).equals("188089999")){//TODO 等第三方企业确定了，需要增加BizSystemCode的子集
			orderBaseData.setAppId(BizSystemCode.DzApp.value());
		}
		Long min = StringUtil.dateMinusMinLong(now, omsChargerBespeakBillRecord.getStart_time());
		orderBaseData.setBuyNum(new BigDecimal(min));
		orderBaseData.setCardNo(userCard);
		orderBaseData.setCardType(map.get("cardType"));
		orderBaseData.setEndTime(endTime_date);
		orderBaseData.setEquipmentNo(chargerId);
		orderBaseData.setPlantId(charger.getStation_id());
		orderBaseData.setServiceNo(OrderServiceEnum.Reservation.value());
		orderBaseData.setServiceProviderCode(charger.getOper_merchant_id());
		//TODO 查询预约费率号，再根据时间来确定
		BigDecimal a1=new BigDecimal(0.8);
		BigDecimal a2=new BigDecimal(15);
		orderBaseData.setUnitPrice(a1.divide(a2,0,BigDecimal.ROUND_HALF_EVEN));
		orderBaseData.setAuxEquipmentNo("0");
		//查询卡号是不是在白名单里面。
		OmsChargerOfflineWhitelist whitelist_query = new OmsChargerOfflineWhitelist();
		whitelist_query.setCharger_id(chargerId);
		whitelist_query.setUser_pay_card(userCard);
		OmsChargerOfflineWhitelist whitelist = omsChargerOfflineWhitelistDao.findOneExample(whitelist_query, null, null);
		if(whitelist!=null){
			orderBaseData.setTotalPrice(new BigDecimal(0));
		}
		orderBaseDatas.add(orderBaseData);
		//TODO 测试时屏蔽，正式时打开
//		RetVO retVO = orderRpcClient.createOrder(orderBaseDatas);
//		if(retVO==null||!retVO.getRetCode().equals(retVO.SuccessCode)){
//			json.setCode(retVO.FailCode);
//		    json.setMsg("createOrder fail");
//		    responseMsgHeader =data.substring(0, 34)+"55"+data.substring(36);
//		    json.setPojo(responseMsgHeader);
//		    return json;
//		}
//    	String bizData = (String) retVO.getBizData();
//    	CreatedOrderVO createdOrderVO = JSON.parseObject(bizData, CreatedOrderVO.class);
//		omsChargerChargeBillRecord.setThis_amount(Float.valueOf(createdOrderVO.getTotalFee().toString()));
		//更新预约费用表中预约结束时间
		omsChargerBespeakBillRecord.setActual_end_time(now);
		if(whitelist!=null){
			omsChargerBespeakBillRecord.setBespeak_deal_charge(0f);
		}else{
			//TODO 订单中的费用
			omsChargerBespeakBillRecord.setBespeak_deal_charge(0f);
		}
		if(flag==true){
			omsChargerBespeakBillRecordDao.updateObject(omsChargerBespeakBillRecord);
		}else{
			omsChargerBespeakBillRecordDao.save(omsChargerBespeakBillRecord);
		}
		// api_v3.php中的1458行 HttpGetRequest 是调用AS的接口 dzAppURL
		responseMsgBody = "";
		responseMsgHeader = data.substring(0, 2)+"0000"+data.substring(6, 34) + "58" + data.substring(36,50);
		// StringUtil.sendSocket(responseMsgHeader);
		try {
			ev3cMessageService.sendNoWait(ev3c_msgHeader+ev3c_msgBody, chargerId);
		} catch (RetryFailException e) {
			e.printStackTrace();
			json.setCode("400");
			json.setMsg("chargerId " + chargerId + " cancelBespeakReturn sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0103CancelBespeakReturn -> result:cancelBespeakReturn sendNoWait fail! " + e.getMessage());
			return json;
		} catch (CreateConnectionFailException e)
		{
			e.printStackTrace();
			json.setCode("400");
			json.setMsg("chargerId " + chargerId + " cancelBespeakReturn sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0103CancelBespeakReturn -> result:cancelBespeakReturn sendNoWait fail! " + e.getMessage());
			return json;
		} catch (DuplicateInstructionException e) {
			log.error("Send message failure, repeat instruction! e = " + e.getMessage(), e);
			json.setMsg("chargerId " + chargerId + " cancelBespeakReturn sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0103CancelBespeakReturn -> result:cancelBespeakReturn sendNoWait fail! " + e.getMessage());
			return json;
		}
		//TODO 根据用户卡号，判断是调用AS接口还是第三方企业接口
//		String dzFun = "&a=beseakcancle";
//		requestURL = StringUtil.dzAppURL + dzFun + "&dianzhuanghao=" + charger.getQr_code() + "&user_pay_card="
//				+ userCard + "&bespeak_time=" + StringUtil.now14time() + "&dianzhanid=" + charger.getStation_id();
//		StringUtil.httpGetRequest(requestURL);
		json.setCode("200");
		json.setMsg("ok");
		json.setPojo(responseMsgHeader + responseMsgBody);
		return json;
	}

	@Override
	public JsonCommon<String> bespeak(Map<String, String> map) throws Exception{
		protocol_type = map.get("protocol_type");
		protocol_version = map.get("protocol_version");
		String data = map.get("data");
		switch (protocol_type) {
		case "1":
			ev3c_frameCode = "14";
			switch (protocol_version) {
			case "0101":
				json = ev3c0101Bespeak(map, data);
				break;
			case "0102":
				// 信息头
				json = ev3c0102Bespeak(map, data);
				// 有信息体
				break;
//			case "0103":
//				// 有信息头，无信息体
//				json = ev3c0103Bespeak(map, data);
//				break;
			case "0201":
				json = ev3c0201Bespeak(map);
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
		return json;
	}

	/**
	 * 针对0101或0102 版本协议
	 * 预约执行流程如下:
	 * 1.判断该枪口状态,若为空闲状态可预约成功,进入第二步;否则:接口直接返回预约失败信息
     * 2.生成预约流水号和状态为预约已下发,入库预约记录表,并更新直流或交流表信息(使用锁,保证数据一致性)
     * 3.下发报文
     *
     * 预约记录表,预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
     *
     * 特别地:预约开始时,查询预约费用表和充电费用表:如果有未支付订单(存在订单号而且未支付),则不允许预约;
     * 如果有,则调用订单服务器接口把未支付订单号列表提供给OS,查询后确认这些是否已支付:如果已支付,就回写数据库相关记录,并允许预约
   	 *
	 * @param map
	 * @param data
	 * @return JsonCommon<String>
	 */
	private JsonCommon<String> ev3c0101Bespeak(Map<String, String> map, String data) {
		log.info("Receive response message from bespeak! curTime = " + new Date().getTime());
		String chargerId, portNo, userCard;
		chargerId = map.get("chargerId");
		portNo = map.get("portNo");
		portNo = Ev3cEncapsulationServiceImpl.portNoWithMsg(portNo);
		userCard = map.get("userCard");
		String serialNo = serialGenerater.generateSerialNo14(); // 序列号
		// 1.组装发下报文
	    String ev3c_msgBody = (portNo.length() == 1 ? "0".concat(portNo):portNo).concat(userCard); // 00表示A口,01表示B口
		String ev3c_msgHeader = "68" + StringUtil.ev3cMsgBodyBin(ev3c_msgBody) + "01" + "000000" + "0001" + chargerId
				+ "14" + serialNo;
		if (StringUtil.isBlank(chargerId) || StringUtil.isBlank(portNo) || StringUtil.isBlank(userCard)) {
			json.setCode(OmsConstant.ErrorCodeEnum.MessageMissParam.value());
			json.setMsg(OmsConstant.ErrorCodeEnum.MessageMissParam.desc());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Charger id do not exist!");
			return json;
		}
		portNo = Ev3cEncapsulationServiceImpl.portNoWithDb(portNo);

		// 2.判断该枪口状态,若为空闲状态可预约成功(预约采用独占试,考虑到并发,查询枪口状态和入库两个操作必须控制在同一把锁来处理,防止脏数据)
		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(portNo, 2);
		OmsCharger charger = (OmsCharger) omsChargerDao.findOneExample(charger_query, null, null);
		/** 0:空闲  1:预约  2:充电  3:故障  4:占用中(针对双枪单充等情况) 5:刷卡中  8:离线*/
		int chargeStatus = 0; // 当前桩,对应枪口状态
		int chargerType = 1; // 1:直流  2:交流  3:混合
		OmsChargerStateDirect directState = null; // 直流表信息
		OmsChargerStateAlternate alternateState = null; // 交流表信息

		// 特别地:预约开始时,查询预约费用表和充电费用表:如果有未支付订单(存在订单号而且未支付),则不允许预约;
	    // 如果有,则调用订单服务器接口把未支付订单号列表提供给OS,查询后确认这些是否已支付:如果已支付,就回写数据库相关记录,并允许预约
		if (!this.checkBespeakOrderNoPayInfo(userCard)) {
			json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value()); // 失败错误码
			json.setMsg("chargerId " + chargerId + " userCard " + userCard + " Exist not pay order!");
			log.error("chargerId " + chargerId + " userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order!");
			return json;
		}

		if (!this.checkChargerOrderNoPayInfo(userCard)) {
			json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value()); // 失败错误码
			json.setMsg("chargerId " + chargerId + " userCard " + userCard + " Exist not pay order!");
			log.error("chargerId " + chargerId + " userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order!");
			return json;
		}

		try {
			lock.lock(); // 得到锁
			// 2.1查询枪口当前状态
			if (charger.getCharger_type() != null) {
				chargerType = charger.getCharger_type();
				switch (chargerType) { // 1:直流  2:交流  3:混合
				case 1:
					OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
					directState_query.setPort_no(port_no);
					directState_query.setCharger_id(map.get("chargerId"));
					directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
					chargeStatus = directState.getCharge_status();
					break;
				case 2:
					OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
					alternateState_query.setPort_no(port_no);
					alternateState_query.setCharger_id(chargerId);
					alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
					chargeStatus = alternateState.getCharge_status();
					break;
				default:
					break;
				}

				if (chargeStatus == 0) { // 当前桩,对应枪口状态为空闲
					log.info("Receive response message from bespeak(chargeStatus is free)");
					// 3.1处理预约记录表
					OmsChargerBespeakBillRecord billRecord = new OmsChargerBespeakBillRecord();
					Date now = new Date();
					String bespeak_jrnl = "";
					bespeak_jrnl = chargerId + "0" + port_no + serialGenerater.generateSerialNo(); // 生成流水号  bespeak_jrnl
					billRecord.setBespeak_jrnl(bespeak_jrnl); // 操作流水号:OMS自动根据时间\电桩地址和其他规则生成;此字段用来关联充电费用记录。0000000000为非真实数据。
					String oms_msg_charge_jrnl = serialNo;
					billRecord.setOms_msg_bespeak_jrnl(oms_msg_charge_jrnl); // 报文开始预约流水号,系统生成,格式为:YYYY-MM-DD-HH-MI-SS加上四位序号,例如:0x20 0x15 0x05 0x
					billRecord.setCharger_id(map.get("chargerId").toString());
					billRecord.setPort_no(port_no); // 枪口号
					billRecord.setUser_pay_card(userCard); // 用户卡号
					billRecord.setStation_id(charger.getStation_id()); // 电站id
					billRecord.setValid_flag(1); // 0:代表已删除,1:代表未删除 
					billRecord.setStart_time(now); // 预约开始时间
					billRecord.setIs_done(0); // 是否完成订单(0:未完成 ,1:完成 )
					billRecord.setEstimate_end_time(null); // 预约理论结束时间 或+6个小时
					billRecord.setBespeak_deal_charge(null); // 最终预约结算费用
					billRecord.setStatus(1); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
					omsChargerBespeakBillRecordDao.save(billRecord);
				} else { // 否则:接口直接返回预约失败,不下发报文
					json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultChargerBespeaked.value());
					json.setMsg("chargerId " + chargerId + "userCard " + userCard + " ev3c0101Bespeak: The charger has been booking!"); // 带卡号
					log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:The charger has been booking!");
					return json;
				}
			} else { // 桩类型错误
				json.setCode(OmsConstant.ErrorCodeEnum.SystemServiceException.value());
				json.setMsg("chargerId " + chargerId + "userCard " + userCard + " ev3c0101Bespeak: charger typy is error!");
				log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:The charger has been booking!");
				return json;
			}
		} catch (Exception e) {
			json.setCode(OmsConstant.ErrorCodeEnum.SystemServiceException.value());
			json.setMsg("chargerId " + chargerId + "userCard " + userCard + " ev3c0101Bespeak: The charger has been booking! " + e.getMessage()); // 带卡号
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:The charger has been booking! " + e.getMessage());
			return json;
		} finally {
			lock.unlock(); // 释放锁
		}

		// 4.下发报文
		try {
			log.info("Send message to bespeak sendNoWait! curTime = " + new Date().getTime());
			ev3cMessageService.sendNoWait(ev3c_msgHeader + ev3c_msgBody, chargerId);

			json.setCode("200"); // 成功返回码
			json.setMsg(chargerId + " bespeak sendSocket success!");
			log.debug("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:bespeak sendSocket success!");
		} catch (RetryFailException e) {
			json.setCode("400"); // 失败错误码
			json.setMsg("chargerId " + chargerId + " bespeak sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:bespeak sendSocket fail! " + e.getMessage());
		} catch (CreateConnectionFailException e) {
			json.setCode("400"); // 失败错误码
			json.setMsg("chargerId " + chargerId + " ev3c0101Bespeak sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:bespeak sendSocket fail! " + e.getMessage());
		} catch (DuplicateInstructionException e) {
			log.error("Send message failure, repeat instruction! e = " + e.getMessage(), e);
			json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultChargerBespeaked.value()); // 失败错误码
			json.setMsg("chargerId " + chargerId + " ev3c0101Bespeak sendSocket fail " + e.getMessage());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:bespeak sendSocket fail! " + e.getMessage());
		}

		return json;
	}

	private JsonCommon<String> ev3c0102Bespeak(Map<String, String> map, String data) {
		return ev3c0101Bespeak(map, data);
	}

	private JsonCommon<String> ev3c0103Bespeak(Map<String, String> map, String data) {
		String chargerId, portNo, userCard, bespeakMinute;
		chargerId = map.get("chargerId");
		portNo = map.get("portNo");
		userCard = map.get("userCard");
		bespeakMinute = map.get("bespeakMinute");//单位：分  例：预约2小时30分钟   bespeakMinute = 150   实际传输数据为：0x96 0x00
		//
		if(bespeakMinute ==null){
			bespeakMinute =String.valueOf(60*60*6);
		}
		String key = chargerId+portNo+userCard;
		RedisClient.delByKey(key);
		RedisClient.putString(key, bespeakMinute);
		int bespeakMinute_int = Integer.valueOf(bespeakMinute);
		RedisClient.expire(key, bespeakMinute_int * 60 + 600);//过期时间在原时间基础上加10分钟
		String ev3c_msgBody = portNo + userCard + StringUtil.float10to16ByParamDesc(bespeakMinute, 1, 4);// 00表示A口，01表示B口
		String ev3c_msgHeader = "68" + StringUtil.ev3cMsgBodyBin(ev3c_msgBody) + "01" + "000000" + "0001"
				+ chargerId + "14" + StringUtil.now14time();
//		StringUtil.sendSocket(msgHeader + msgBody);//
		try {
			ev3cMessageService.sendNoWait(ev3c_msgHeader+ev3c_msgBody, chargerId);
		} catch (RetryFailException e) {
			e.printStackTrace();
			json.setCode("400");
			json.setMsg("chargerId "+ chargerId +" bespeak sendSocket fail "+e.getMessage());
			return json;
		}
		catch (CreateConnectionFailException e)
		{
			e.printStackTrace();
			json.setCode("400");
			json.setMsg("chargerId "+ chargerId +" cancelBespeakReturn sendSocket fail "+e.getMessage());
			return json;
		} catch (DuplicateInstructionException e) {
			log.error("Send message failure, repeat instruction! e = " + e.getMessage(), e);
			json.setCode("400");
			json.setMsg("chargerId "+ chargerId +" cancelBespeakReturn sendSocket fail "+e.getMessage());
			return json;
		}
		JsonCommon<String> json = new JsonCommon<String>();
		json.setCode("200");
		json.setMsg(chargerId + " bespeak sendSocket success");
		return json;
	}

	private JsonCommon<String> ev3c0201Bespeak(Map<String, String> map) throws Exception
	{
		String chargerId,  userCard,  frameCode, chargerType = "", encryption, msg;

		log.info(map);
		frameCode = "11";
		chargerId = map.get("chargerId");
		int portNo = Integer.valueOf(map.get("portNo"));
		userCard = map.get("userCard");
		encryption = map.get("encryption");
		if(StringUtil.isBlank(chargerId)||!StringUtil.isNumeric(map.get("portNo"))||StringUtil.isBlank(userCard))
			throw new BizException("Charger id do not exist");

		if(StringUtil.isBlank(encryption)){
			encryption ="00";
		}

		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		if(charger == null)
			throw new BizException("Charger id do not exist");
		log.info(charger.getCharger_id());

		chargerType = String.valueOf(charger.getCharger_type());
		StringBuffer sql = new StringBuffer();
		sql.append(" select a.online_status, a.charge_status from oms_charger_state_alternate a ");
		sql.append(" where a.charger_id = ? and a.port_no = ? ");
		sql.append(" union ALL ");
		sql.append(" select d.online_status, d.charge_status from oms_charger_state_direct d ");
		sql.append(" where d.charger_id = ? and d.port_no = ? ");
		List<Map<String, Object>> list_charger_status = omsChargerDao.findDataBySql(sql.toString(), chargerId, portNo, chargerId, portNo);
		if(list_charger_status != null && !list_charger_status.isEmpty())
		{
			Map<String, Object> charger_status = list_charger_status.get(0);
			if ((Integer)charger_status.get("online_status") != 1 || (Integer)charger_status.get("charge_status") != 0 )
				throw new BizException(MessageFormat.format("Charger status wrong online_status = {0}, charge_status = {1}", charger_status.get("online_status"), charger_status.get("charge_status")));
		}

		log.info("Valid status");

		if (!this.checkBespeakOrderNoPayInfo(userCard) || !this.checkChargerOrderNoPayInfo(userCard)){
			json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value()); // 失败错误码
			json.setMsg("chargerId " + chargerId + " userCard " + userCard + " Exist not pay order!");
			log.error("chargerId " + chargerId + " userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0201Bespeak -> result:Exist not pay order!");
			return json;
		}
			//throw new BizException("There is unpaid order for this card");

		String random_code = Ev3c2EncapsulationServiceImpl.getRandom4int();

		int bespeakMinute = DEFAULT_BESPEAK_MINITUE;//单位：分  例：预约2小时30分钟   bespeakMinute = 150   实际传输数据为：0x96 0x00

		//		RedisClient.expire(key, bespeakMinute_int * 60 + 600);//过期时间在原时间基础上加10分钟
		String ev3c_msgBody = userCard + StringUtil.float10to16ByParamDesc(String.valueOf(bespeakMinute), 1, 4) + random_code;// 00表示A口，01表示B口

		msg = messageWapper.wrapSendingMsg(ev3c_msgBody, frameCode, chargerId, chargerType, String.valueOf(portNo), encryption);

		String key = msg.substring(32, 50);//以开始预约作为key放入redis中

		//写数据库
		OmsChargerBespeakBillRecord billRecord = new OmsChargerBespeakBillRecord();
		//规则：桩号+端口号+14位时间，其中端口号为两位，以01开始。
		String bespeak_jrnl = "";

		bespeak_jrnl = chargerId + String.format("%02d", portNo) + serialGenerater.generateSerialNo();//portNo应该是2位

		billRecord.setBespeak_jrnl(bespeak_jrnl);
		billRecord.setOms_msg_bespeak_jrnl(key);
		billRecord.setUser_pay_card(userCard);
		billRecord.setPort_no(portNo);
		billRecord.setStart_time(new Date());
		billRecord.setStation_id(charger.getStation_id());

		billRecord.setCharger_id(chargerId);
		billRecord.setIs_done(0);
		billRecord.setStatus(OmsConstant.BespeakStatus.Reserving);
		billRecord.setValid_flag(1);
		omsChargerBespeakBillRecordDao.save(billRecord);

		log.info(billRecord);

		try
		{
//			RedisClient.getJedisInstance().set(key, JSON.toJSONString(billRecord));
//			RedisClient.expire(key, bespeakMinute * 60 + 600);//过期时间在原时间基础上加10分钟
			ev3c2MessageService.sendNoWait(msg, chargerId);
		}
		catch (RetryFailException e)
		{
			log.error(e.getMessage(), e);
			throw e;
		}
		catch (CreateConnectionFailException e)
		{
			log.error(e.getMessage(), e);
			throw e;
		}
		JsonCommon<String> json = new JsonCommon<>();
		json.setCode("200");
		json.setMsg(chargerId + " bespeak sendSocket success");
		return json;
	}


	@Override
	public JsonCommon<String> cancelBespeak(Map<String, String> map) throws Exception
	{

		protocol_type = map.get("protocol_type");
		protocol_version = map.get("protocol_version");
		String data = map.get("data");
		switch (protocol_type) {
		case "1":
			ev3c_frameCode = "14";
			switch (protocol_version) {
			case "0101":
				json = ev3c0101CancelBespeak(map, data);
				break;
			case "0102":
				json = ev3c0102CancelBespeak(map, data);
				break;
//			case "0103":
//				json = ev3c0103CancelBespeak(map, data);
//				break;
			case "0201":
				json = ev3c0201CancelBespeak(map, data);
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
		return json;
	}

	/**
	 * 针对0101或0102 版本协议
	 * 执行流程如下:
	 * 取消预约(不充电):
	 * 1.判断当前枪口状态,如果为非预约中,则直接返回接口。
	 * 2.更新预约记录表(取消预约中)
	 * 3.下发报文
	 *
	 * 取消预约如果是转为充电,则不调用订单服务器,待充电完成后生成一笔订单(包括充电和预约信息)
	 *
	 * @param map
	 * @param data
	 * @return
	 */
	private JsonCommon<String> ev3c0101CancelBespeak(Map<String, String> map, String data) {
		log.info("Receive response message from cancelBespeak" + new Date().getTime());
		String chargerId, portNo, userCard, bespeakStartSerialNumber;
		chargerId = map.get("chargerId");
		portNo = map.get("portNo");
		userCard = map.get("userCard");
		bespeakStartSerialNumber = map.get("bespeakStartSerialNumber");
		if(StringUtil.isBlank(chargerId)||!StringUtil.isNumeric(map.get("portNo"))||StringUtil.isBlank(userCard)) {
			json.setCode(OmsConstant.ErrorCodeEnum.MessageMissParam.value());
			json.setMsg(OmsConstant.ErrorCodeEnum.MessageMissParam.desc());
			log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101CancelBespeak -> result:Charger id do not exist!");
			return json;
		}

		portNo = Ev3cEncapsulationServiceImpl.portNoWithDb(portNo);
		// 1.判断当前枪口状态,如果为非预约中,则直接返回接口
		// [判断该枪口状态,若为空闲状态可预约成功(预约采用独占试,考虑到并发,查询枪口状态和入库两个操作必须控制在同一把锁来处理,防止脏数据)]
		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		int port_no = Integer.parseInt(portNo, 2);
		OmsCharger charger = (OmsCharger) omsChargerDao.findOneExample(charger_query, null, null);
		/** 0:空闲  1:预约  2:充电  3:故障  4:占用中(针对双枪单充等情况) 5:刷卡中  8:离线*/
		int chargeStatus = 0; // 当前桩,对应枪口状态
		int chargerType = 1; // 1:直流  2:交流  3:混合
		OmsChargerStateDirect directState = null; // 直流表信息
		OmsChargerStateAlternate alternateState = null; // 交流表信息

		log.info("Receive response message from cancelbespeak(charger_query)");

		// 2.1查询枪口当前状态
		if (charger.getCharger_type() != null) {
			chargerType = charger.getCharger_type();
			switch (chargerType) { // 1:直流  2:交流  3:混合
			case 1:
				OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
				directState_query.setPort_no(port_no);
				directState_query.setCharger_id(map.get("chargerId"));
				directState = (OmsChargerStateDirect) omsChargerStateDirectDao.findOneExample(directState_query, null, null);
				chargeStatus = directState.getCharge_status();
				directState.setBespeak_jrnl(null); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
				directState.setUser_pay_card(null);
				omsChargerStateDirectDao.updateObject(directState);
				break;
			case 2:
				OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
				alternateState_query.setPort_no(port_no);
				alternateState_query.setCharger_id(chargerId);
				alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
				chargeStatus = alternateState.getCharge_status();
				alternateState.setBespeak_jrnl(null); // 下发报文预约开始流水号(报文开始预约流水号,系统生成,:格式为:YYYY-MM-DD-HH-MI-SS加上四位序号 例如：0x20 0x15 0x05 0x10 0x21 0x45 0x34,0x00,0x00表示2015年5月10日21点击5分34秒第一个流水号(同一时刻自增))
				alternateState.setUser_pay_card(null);
				omsChargerStateDirectDao.updateObject(alternateState);
				break;
			default:
				break;
			}

			// 3.处理预约记录表,更新状态
			OmsChargerBespeakBillRecord bespeakBillRecord_query = new OmsChargerBespeakBillRecord();
			if (StringUtil.isEmpty(bespeakStartSerialNumber)) { // true:为空  false:不为空, 接口取消预约
				bespeakBillRecord_query.setOms_msg_bespeak_jrnl(bespeakStartSerialNumber);
			} else {
				bespeakBillRecord_query.setUser_pay_card(userCard);
				bespeakBillRecord_query.setStatus(2); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
				bespeakBillRecord_query.setCharger_id(chargerId);
				bespeakBillRecord_query.setPort_no(port_no);
			}
			OmsChargerBespeakBillRecord bespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExample(bespeakBillRecord_query,"start_time","desc");
			if (!StringUtil.objectIsNull(bespeakBillRecord) && bespeakBillRecord.getStatus() == 2) { // 状态为已预约,则可以取消预约
				bespeakBillRecord.setStatus(3); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
				bespeakBillRecord.setOms_msg_bespeak_end_jrnl(serialGenerater.generateSerialNo());
				omsChargerBespeakBillRecordDao.updateObject(bespeakBillRecord); // 更新状态
			} else { // 否则:接口直接返回取消预约失败
				json.setCode(OmsConstant.ErrorCodeEnum.CancelBespeakResultNoBespeak.value());
				json.setMsg("chargerId " + chargerId + "userCard " + userCard + " ev3c0101Bespeak: The charger no bespeak!"); // 带卡号
				log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:The charger no bespeak!");
			}

			// 3.下发报文
			portNo = Ev3cEncapsulationServiceImpl.portNoWithMsg(portNo);
			String ev3c_msgBody = (portNo.length() == 1 ? "0".concat(portNo):portNo).concat(userCard); // 00表示A口,01表示B口
			String ev3c_msgHeader = "68" + StringUtil.ev3cMsgBodyBin(ev3c_msgBody) + "01" + "000000" + "0001"
					+ chargerId + "16" + StringUtil.now14time();
			try {
				log.info("Send message to cancelBespeak sendNoWait! curTime = " + new Date().getTime());
				ev3cMessageService.sendNoWait(ev3c_msgHeader+ev3c_msgBody, chargerId);
			} catch (RetryFailException e) {
				json.setCode("400");
				json.setMsg("chargerId " + chargerId + " cancelBespeak sendSocket fail! " + e.getMessage());
				log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101CancelBespeak -> result:cancelBespeak sendNoWait fail!" + e.getMessage());
				return json;
			} catch (CreateConnectionFailException e) {
				json.setCode("400");
				json.setMsg("chargerId " + chargerId + " cancelBespeakReturn sendSocket fail " + e.getMessage());
				log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101CancelBespeak -> result:cancelBespeak sendNoWait fail!" + e.getMessage());
				return json;
			} catch (DuplicateInstructionException e) {
				log.error("Send message failure, repeat instruction! e = " + e.getMessage(), e);
				json.setCode("400");
				json.setMsg("chargerId " + chargerId + " cancelBespeakReturn sendSocket fail " + e.getMessage());
				log.error("chargerId " + chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101CancelBespeak -> result:cancelBespeak sendNoWait fail!" + e.getMessage());
				return json;
			}

			json.setCode("200");
			json.setMsg("bespeak sendSocket success");
			json.setPojo(ev3c_msgHeader + ev3c_msgBody);
			log.debug("chargerId "+ chargerId + " Class:OmsBespeakServiceImpl -> method:ev3c0101CancelBespeak -> result:cancelBespeak sendOrderToAppServer success, cancelBespeak sendSocket success!");
		  }
		return json;
	}

	private JsonCommon<String> ev3c0102CancelBespeak(Map<String, String> map, String data) {
		return ev3c0101CancelBespeak(map, data);
	}

	private JsonCommon<String> ev3c0103CancelBespeak(Map<String, String> map, String data) {
		return ev3c0101CancelBespeak(map, data);
	}

	private synchronized JsonCommon<String> ev3c0201CancelBespeak(Map<String, String> map, String data) throws Exception
	{
		log.info("Cancel reservation");

		String bespeakStartSerialNumber = map.get("bespeakStartSerialNumber");
		log.info(bespeakStartSerialNumber);

		OmsChargerBespeakBillRecord billRecord_query = new OmsChargerBespeakBillRecord();
		billRecord_query.setOms_msg_bespeak_jrnl(bespeakStartSerialNumber);
		billRecord_query.setStatus(OmsConstant.BespeakStatus.Reserved);
		OmsChargerBespeakBillRecord billRecord = omsChargerBespeakBillRecordDao.findOneExample(billRecord_query, null, null);
		if (billRecord == null)
			throw new BizException("Reservation record not found");
		log.info("reservation record found");

		String userCard = billRecord.getUser_pay_card();
		String chargerId = billRecord.getCharger_id();
		Integer portNo = billRecord.getPort_no();

		String frameCode = "12";
		String encryption = "00";

		String ev3c_msgBody = userCard + bespeakStartSerialNumber;// 00表示A口，01表示B口

		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		if (charger == null)
			throw new BizException("Charger is not found ");
		log.info(charger.getCharger_id());

		if (StringUtils.isNotEmpty(billRecord.getOrder_no()))
			throw new BizException("Cannot cancel this reservation because it is already generated as an order");
		log.info("Haven't create a order");

		String msg = messageWapper.wrapSendingMsg(ev3c_msgBody, frameCode, chargerId, String.valueOf(charger.getCharger_type()), portNo.toString(), encryption);

		billRecord.setOms_msg_bespeak_end_jrnl(msg.substring(32, 50));
		billRecord.setStatus(OmsConstant.BespeakStatus.ReservationCancelling);
		omsChargerBespeakBillRecordDao.updateObject(billRecord);

		log.info(billRecord);
		try
		{
			ev3c2MessageService.sendNoWait(msg, chargerId);
		}
		catch (RetryFailException e)
		{
			log.error(e.getMessage(), e);
			throw e;
		}
		catch (CreateConnectionFailException e)
		{
			log.error(e.getMessage(), e);
			throw e;
		}
		JsonCommon<String> json = new JsonCommon<String>();
		json.setCode("200");
		json.setMsg("bespeak sendSocket success");
		log.info(json);
		return json;
	}

	//2.0协议中的预约返回就表示预约已经成功，桩状态已经改变。预约下发的时候在预约费用表中生成一条记录，记录下发的流水号和表中生成的流水号。下发流水号由Java控制唯一。
	//预约下发时已经把预约信息存入表中，不在redis中做处理
	@Override
	public void ev3c02bespeakReturn(ChargerReplyMsgHeader header) throws Exception
	{
		log.info("Receive response message from charger");
		log.debug(JSON.toJSON(header));

		String omsSerialNumber = header.getServerSerialNo();

		// 之前是char_bespeak_record，现在这个表已经被合并到char_bespeak_bill_record[预约费用记录表]中了。
		OmsChargerBespeakBillRecord billRecord_query = new OmsChargerBespeakBillRecord();
		billRecord_query.setOms_msg_bespeak_jrnl(omsSerialNumber);
		OmsChargerBespeakBillRecord billRecord = omsChargerBespeakBillRecordDao.findOneExample(billRecord_query, null, null);
		if (billRecord == null)
			throw new BizException("Reservation record not found");

		log.info("reservation record exist");

		String chargerId = billRecord.getCharger_id();
		int port_no = billRecord.getPort_no();

		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		if(charger == null)
			throw new BizException("Charger not found");

		log.info("charger exist");

		billRecord.setStatus(OmsConstant.BespeakStatus.Reserved);//预约已回复，桩状态为预约中
		omsChargerBespeakBillRecordDao.updateObject(billRecord);
		// 更新状态 oms_charger_state_alternate[交流充电桩状态表]
		// oms_charger_state_direct[直流充电桩状态表]
		// 报文中需要有直流和交流的区别，如果是为了中新用的，就应该是oms_charger_state_direct[直流充电桩状态表]
		if (charger.getCharger_type() != null)
		{
			int chargerType = charger.getCharger_type();
			log.info(chargerType);
			switch (chargerType)
			{// 1--直流 2--交流 3--混合
				case 1:
					OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
					directState_query.setPort_no(port_no);
					directState_query.setCharger_id(header.getChargerId());
					OmsChargerStateDirect directState = omsChargerStateDirectDao.findOneExample(directState_query, null, null);
					directState.setCharge_status(1);
					directState.setOnline_status(1);
					directState.setBespeak_jrnl(billRecord.getBespeak_jrnl());
					directState.setUser_pay_card(billRecord.getUser_pay_card());
					omsChargerStateDirectDao.updateObject(directState);
					if (charger.getIs_parallel_charge() == 0)
					{
						omsChargerStateDirectDao.exec("update oms_charger_state_direct set charge_status = 4 where charger_id = '" + chargerId + "' and port_no <> " + port_no);
					}
					break;
				case 2:
					OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
					alternateState_query.setPort_no(port_no);
					alternateState_query.setCharger_id(chargerId);
					OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
					alternateState.setCharge_status(1);
					alternateState.setOnline_status(1);
					alternateState.setBespeak_jrnl(billRecord.getBespeak_jrnl());
					alternateState.setUser_pay_card(billRecord.getUser_pay_card());
					omsChargerStateAlternateDao.updateObject(alternateState);
					if (charger.getIs_parallel_charge() == 0)
					{
						omsChargerStateDirectDao.exec("update oms_charger_state_alternate set charge_status = 4 where charger_id = '" + chargerId + "' and port_no <> " + port_no);
					}
					break;
				default:
					break;
			}
		}

		// api_v3.php中的1458行 HttpGetRequest 是调用AS的接口 dzAppURL,通知
		log.info("Notify AS");
		// 通知appServer start
		try
		{
			notifyOnReservationSuccess(AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_RESERVATION, billRecord, charger);
		}
		catch (BizException e)
		{
			log.error(e.getMessage(), e);
		}
		log.info("After Notify");

	}
	//开始预约下发时不存预约开始时间，开始预约返回时存预约开始时间，预约时长。取消预约下发时不存预约结束时间，返回时存预约结束时间。
	@Override
	public void ev3c2cancelBespeakReturn(ChargerReplyMsgHeader header) throws Exception
	{

		log.info("reservation return");
		String omsSerialNumber = header.getServerSerialNo();
		log.info(omsSerialNumber);

		OmsChargerBespeakBillRecord omsChargerBespeakBillRecord_query = new OmsChargerBespeakBillRecord();
		omsChargerBespeakBillRecord_query.setOms_msg_bespeak_end_jrnl(omsSerialNumber);
		OmsChargerBespeakBillRecord bespeakBill = omsChargerBespeakBillRecordDao.findOneExample(omsChargerBespeakBillRecord_query, null, null);
		if (bespeakBill == null)
			throw new BizException("Reservation record not found");

		String chargerId = bespeakBill.getCharger_id();
		Integer port_no = bespeakBill.getPort_no();

		OmsCharger charger_query = new OmsCharger();
		charger_query.setCharger_id(chargerId);
		OmsCharger charger = omsChargerDao.findOneExample(charger_query, null, null);
		if (charger == null || charger.getCharger_type() == null)
			throw new BizException("Charger not found or charger type is empty");

		int chargerType = charger.getCharger_type();
		log.info(chargerType);
		switch (chargerType)
		{// 1--直流 2--交流 3--混合
			case 1:
				OmsChargerStateDirect directState_query = new OmsChargerStateDirect();
				directState_query.setPort_no(port_no);
				directState_query.setCharger_id(chargerId);
				OmsChargerStateDirect directState = omsChargerStateDirectDao.findOneExample(directState_query, null, null);
				directState.setCharge_status(0);
				directState.setOnline_status(1);
				directState.setBespeak_jrnl("");
				omsChargerStateDirectDao.updateObject(directState);
				if (charger.getIs_parallel_charge() == 0)
				{
					omsChargerStateDirectDao.exec("update oms_charger_state_direct set charge_status = 4 where charger_id = '" + chargerId + "' and port_no <> " + port_no);
				}
				break;
			case 2:
				OmsChargerStateAlternate alternateState_query = new OmsChargerStateAlternate();
				alternateState_query.setPort_no(port_no);
				alternateState_query.setCharger_id(chargerId);
				OmsChargerStateAlternate alternateState = omsChargerStateAlternateDao.findOneExample(alternateState_query, null, null);
				alternateState.setCharge_status(0);
				alternateState.setOnline_status(1);
				alternateState.setBespeak_jrnl("");
				omsChargerStateAlternateDao.updateObject(alternateState);
				if (charger.getIs_parallel_charge() == 0)
				{
					omsChargerStateDirectDao.exec("update oms_charger_state_alternate set charge_status = 0 where charger_id = '" + chargerId + "' and port_no <> " + port_no);
				}
				break;
			default:
				break;
		}

		Date now = new Date();
//		String userCard = bespeakBill.getUser_pay_card();


//		String cardType = CardUtils.generateCardType(userCard);

		BigDecimal totalAmount = BigDecimal.ZERO;

		//查询卡号是不是在白名单里面。
		OmsChargerOfflineWhitelist whitelist_query = new OmsChargerOfflineWhitelist();
		whitelist_query.setCharger_id(chargerId);
		whitelist_query.setUser_pay_card(bespeakBill.getUser_pay_card());
		OmsChargerOfflineWhitelist whitelist = omsChargerOfflineWhitelistDao.findOneExample(whitelist_query, null, null);
		List<PaymentDetail> reservationFeeDetails = new ArrayList<>();
		if (whitelist == null)
			totalAmount = priceService.computeFee(charger.getRate_schema_bespeak_fee(), bespeakBill.getStart_time(), now, reservationFeeDetails);

		if (totalAmount.compareTo(new BigDecimal(OrderConstant.UPLOAD_BILL_CHARGE_BESPEAK_MAX)) > 0)
		{
			// 入库oms_charger_error_record[故障记录表]
			log.error("Bespeak fee exception!");
			OmsChargerErrorRecord record = new OmsChargerErrorRecord();
			record.setCharger_id(chargerId);
			record.setError_code("error");
			record.setError_msg("Bespeak fee exception!");
			record.setStatus(0); // 0:未处理,1:已处理
			record.setValid_flag(1);
			record.setCreate_oper_id("000");
			record.setCreate_time(new Date());
			omsChargerErrorRecordService.add(record);
			throw new BizException("Bespeak fee exception " + totalAmount);
		}

		bespeakBill.setActual_end_time(new Date());
		bespeakBill.setStatus(OmsConstant.BespeakStatus.ReservationCancelled);
		bespeakBill.setBespeak_deal_before(totalAmount.floatValue());

		RetVO.CreatedOrderVO createdOrderVO = this.createOrderWhenCancelReservation(bespeakBill, charger, reservationFeeDetails);

		bespeakBill.setOrder_no(createdOrderVO.getOrderNo());
		bespeakBill.setBespeak_deal_charge(createdOrderVO.getTotalFee().floatValue());
		omsChargerBespeakBillRecordDao.updateObject(bespeakBill);

		log.info(bespeakBill);

		try
		{
			notifyOnReservationSuccess(AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_CANCEL_RESERVATION, bespeakBill, charger);
			notifyOnReservationFee(createdOrderVO, bespeakBill);
		}
		catch (BizException e)
		{
			log.error(e.getMessage(), e);
		}
	}

	/*****************20160411 perlin add begin**************************************/
	@Override
	public JsonForList<OmsChargerBespeakBillRecord> findBespeakBySeriaNoAndUserCard(String userPayCard, String bespeak_serial_number) {
		String conditonSql = " a where a.user_pay_card = '"+userPayCard + "' and a.bespeak_jrnl='"+bespeak_serial_number+"'";
		OmsChargerBespeakBillRecord queryObj = this.omsChargerBespeakBillRecordDao.findOneExampleByCondition(new OmsChargerBespeakBillRecord(), conditonSql);
		JsonForList<OmsChargerBespeakBillRecord> retJsons = new JsonForList<OmsChargerBespeakBillRecord>();
		if(null==queryObj){
			retJsons.setCode(MsgCodeEnum.AS_RPC_PARAM_FORMAT_ERROR.getMsgCode());
			retJsons.setMsg(MsgCodeEnum.AS_RPC_PARAM_FORMAT_ERROR.getMsgInfo());
			return retJsons;
		}
		List<OmsChargerBespeakBillRecord> lsRecords = new ArrayList<OmsChargerBespeakBillRecord>();
		lsRecords.add(queryObj);

		retJsons.setCode(MsgCodeEnum.SUCCESS.getMsgCode());
		retJsons.setMsg(MsgCodeEnum.SUCCESS.getMsgInfo());
		retJsons.setList(lsRecords);
		return retJsons;
	}

	@Override
	public JsonForList<OmsChargerBespeakBillRecord> findListByUserCard(	String userPayCard, String pageNo, String pageSize) {
		String conditonSql = " a where a.user_pay_card = '"+userPayCard + "'";
		JsonForList<OmsChargerBespeakBillRecord> retJsons = new JsonForList<OmsChargerBespeakBillRecord>();
		retJsons.setCode(MsgCodeEnum.SUCCESS.getMsgCode());
		retJsons.setMsg(MsgCodeEnum.SUCCESS.getMsgInfo());
		retJsons.setList(this.omsChargerBespeakBillRecordDao.findListByPageAndGroupAndOrderAndCondition(new OmsChargerBespeakBillRecord(), conditonSql, Integer.valueOf(pageNo), Integer.valueOf(pageSize), null, null, null));
		return retJsons;
	}
	/*****************20160411 perlin add end**************************************/

	/**
	 * 校验电桩回复报文中响应码
	 * @return boolean
	 */
	public static boolean checkChargerReplyMessageStatus(String responseCode) {
		boolean flag = true;
		// 1.判断回复报文中是否为正常返回,如果响应码不为000000,则做相应处理(记录入故障记录表,再回调);否则进入第二步。
		if (responseCode == null || "".equals(responseCode) || !responseCode.equals("000000")) {
			flag = false;
		}
		return flag;
	}

	/**
	 * 校验卡号类型(1:app 2:)
	 * @return boolean
	 */
	public static int checkUserCardType(String userCard) {
		int result = 0;
		if(userCard.startsWith("18808")&&!userCard.substring(0, 9).equals("188089999")){ // 08:线上卡
			result = 1; // app卡号
		} else if(userCard.startsWith("18806")&&!userCard.substring(0, 9).equals("188060028")){ // 06:现金卡
			result = 2;
		} else if(userCard.startsWith("18805")&&!userCard.substring(0, 9).equals("188050028")){ // 05 身份认证卡
			result = 3;
		}
		return result;
	}

	@Override
	public List<OrdersStatus> getOrdersStatus(String orderNos) throws BizException {
		log.info("Send to  message from  orderRpcClient.createOrder! curTime = " + new Date().getTime());
		//RetVO retVO = orderRpcClient.queryOrderStatus(orderNos);
		RetVO retVO = null;
		if (retVO == null || !retVO.getRetCode().equals(RetVO.SuccessCode))
			throw new BizException("query order status error via order server while querying orders ");

		String bizData = retVO.getBizData().toString();
		log.debug(bizData);
		List<OrdersStatus>  listTmp = JSON.parseArray(bizData, OrdersStatus.class);
		return listTmp;
	}

	@Override
	public boolean updateOrdersStatus(String orderNos,String type) {
		String sql = "";
		if ("1".equals(type)) {
			sql = "update oms_charger_bespeak_bill_record set is_done=1,status=4 where order_no in (" + orderNos + ")"; //预约订单
		}else if ("2".equals(type)) {
			sql = "update oms_charger_charge_bill_record set status=6,offline_is_pay=3 where order_no in (" + orderNos + ")"; //充电订单
		}

		return omsChargerBespeakBillRecordDao.exec(sql);
	}

	/**
	 * 校验预约订单没有支付信息
	 * @return true:不存在没有支付订单
	 */
	public boolean checkBespeakOrderNoPayInfo( String userCard) {
		OmsChargerBespeakBillRecord bespeakBillRecord_query = new OmsChargerBespeakBillRecord();
//		bespeakBillRecord_query.setCharger_id(chargerId);
		bespeakBillRecord_query.setUser_pay_card(userCard);
//		bespeakBillRecord_query.setPort_no(port_no);
		bespeakBillRecord_query.setIs_done(0); // 是否完成订单(0:未完成,1:完成)
		bespeakBillRecord_query.setValid_flag(1);
		List<OmsChargerBespeakBillRecord> omsChargerBespeakBillRecordList = omsChargerBespeakBillRecordDao.findExample(bespeakBillRecord_query, null, null, null, null);

		String orderNoPayList = ""; // 组装订单号发送到订单服务器列表
		List<OrdersStatus> resultList = null;
		int bespeakListFlag = 0; // 未支付状态数量标记
		if (omsChargerBespeakBillRecordList != null && omsChargerBespeakBillRecordList.size() > 0) { // 存在未支付订单(1.预约)
			for (int i = 0; i < omsChargerBespeakBillRecordList.size(); i++) {
				if (omsChargerBespeakBillRecordList.get(i).getOrder_no() != null){ // 订单号不为空,组装
					orderNoPayList = orderNoPayList.concat(omsChargerBespeakBillRecordList.get(i).getOrder_no()).concat(",");
				}
			}
			if (orderNoPayList.length() > 0) {
				orderNoPayList = orderNoPayList.substring(0, orderNoPayList.length() - 1); // 处理最后一个 ,
				try {
					// 发送订单服务器,获取支付信息
					resultList = getOrdersStatus(orderNoPayList); // 调用订单服务器接口
					for (OrdersStatus ordersStatus : resultList) {
						if (ordersStatus.getStatusCode().equals("7")) { // (7, "已支付,已完成")
							OmsChargerBespeakBillRecord bespeakBillRecord_temp = new OmsChargerBespeakBillRecord();
							bespeakBillRecord_temp.setOrder_no(ordersStatus.getOrderNo());
							OmsChargerBespeakBillRecord bespeakBillRecord = omsChargerBespeakBillRecordDao.findOneExample(bespeakBillRecord_temp,null,null);
							bespeakBillRecord.setIs_done(1); // 是否完成订单(0:未完成,1:完成)
							bespeakBillRecord.setStatus(4); // 预约状态:1:预约中  2:已预约  3:取消预约中  4:已取消预约  5:充电(流程1:1-2-3-4, 流程2:1-2-5)
							omsChargerBespeakBillRecordDao.updateObject(bespeakBillRecord);
						} else { // 入库处理
							bespeakListFlag ++;
						}
					}
					if (bespeakListFlag != 0) { // 存在未支付订单(1.预约),直接返回
						json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value()); // 失败错误码
						json.setMsg("userCard " + userCard + " Exist not pay order!");
						log.error("userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order!");
						return false;
					}
				} catch (BizException e) {
					json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value());
					json.setMsg("userCard " + userCard + "userCard " + userCard + " ev3c0101Bespeak:Exist not pay order! " + e.getMessage()); // 带卡号
					log.error("userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order! " + e.getMessage());
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 校验充电订单没有支付信息
	 * @return true:不存在没有支付订单
	 */
	public boolean checkChargerOrderNoPayInfo(String userCard) {
		OmsChargerChargeBillRecord billRecord_query = new OmsChargerChargeBillRecord();
//		billRecord_query.setCharger_id(chargerId);
		billRecord_query.setUser_pay_card(userCard);
//		billRecord_query.setPort_no(port_no);
		billRecord_query.setValid_flag(1);
		billRecord_query.setOffline_is_pay(2); // 0:线下未结算,1:线下已结算,2:线上未结算,3.线上已结算 
		List<OmsChargerChargeBillRecord> omsChargerChargeBillRecordList = omsChargerChargeBillRecordDao.findExample(billRecord_query, null, null, null, null);
		String orderNoPayList = ""; // 组装发送到订单服务器列表
		List<OrdersStatus> resultList = null;
		int chargeListFlag = 0; // 支付标记
		if (omsChargerChargeBillRecordList != null && omsChargerChargeBillRecordList.size() > 0) { // 存在未支付订单(1.预约)
			for (int i = 0; i < omsChargerChargeBillRecordList.size(); i++) {
				if (omsChargerChargeBillRecordList.get(i).getOrder_no() != null){ // 订单号不为空,组装
					orderNoPayList = orderNoPayList.concat(omsChargerChargeBillRecordList.get(i).getOrder_no()).concat(",");
				}
			}
			if (orderNoPayList.length() > 0) {
				orderNoPayList = orderNoPayList.substring(0, orderNoPayList.length() - 1); // 处理最后一个 ,
				try {
					// 发送订单服务器,获取支付信息
					resultList = getOrdersStatus(orderNoPayList); // 调用订单服务器接口
					for (OrdersStatus ordersStatus : resultList) {
						if (ordersStatus.getStatusCode().equals("7")) { // (7, "已支付,已完成")
							OmsChargerChargeBillRecord chargeBillRecord_temp = new OmsChargerChargeBillRecord();
							chargeBillRecord_temp.setOrder_no(ordersStatus.getOrderNo());
							OmsChargerChargeBillRecord chargeBillRecord = omsChargerChargeBillRecordDao.findOneExample(chargeBillRecord_temp,null,null);
							chargeBillRecord.setOffline_is_pay(3); // 0:线下未结算,1:线下已结算,2:线上未结算,3.线上已结算 
							chargeBillRecord.setStatus(6); // 0:开启充电(已下发指令未回复) 1:充电中(已确认桩回复)  2:电充满未结束(如未拔枪则是此状态)  3:关闭充电(已下发指令)  4:充电结束(桩回复充电结束)  5:已生成账单  6:已结算  7:已退款  8:充电失败
							omsChargerChargeBillRecordDao.updateObject(chargeBillRecord);
						} else { // 入库处理
							chargeListFlag ++;
						}
					}
					if (chargeListFlag != 0) { // 存在未支付订单(1.预约),直接返回
						json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value()); // 失败错误码
						json.setMsg("userCard " + userCard + " Exist not pay order!");
						log.error("userCard " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order!");
						return false;
					}
				} catch (BizException e) {
					json.setCode(OmsConstant.ErrorCodeEnum.BespeakResultExistNotPayOrder.value());
					json.setMsg("chargerId " + userCard + " ev3c0101Bespeak:Exist not pay order! " + e.getMessage()); // 带卡号
					log.error("chargerId " + userCard + " Class:OmsBespeakServiceImpl -> method:ev3c0101Bespeak -> result:Exist not pay order! " + e.getMessage());
					return false;
				}
			}
		}
		return true;
	}

	private void notifyOnReservationSuccess(String action, OmsChargerBespeakBillRecord bespeakBillRecord, OmsCharger charger) throws BizException
	{
		String userCard = bespeakBillRecord.getUser_pay_card();
		if (CardUtils.generateCardType(userCard).equals(OmsConstant.CardTypeEnum.OnlineApp))
		{ // APP卡号
			log.info("Receive response message from bespeakReturn(AppReservationNotifyParam)");
			// 通知appServer start
			AppReservationNotifyParam obj = new AppReservationNotifyParam();
			obj.setAction(action);//AppServerConstant.STATION_UPDATE_NOTIFY_ACTION_RESERVATION); // 预约
			obj.setChargerId(bespeakBillRecord.getCharger_id());
			obj.setStationName(charger.getStation_name());
			obj.setSerialNo(charger.getSerial_no());
			obj.setPlugNo(String.valueOf(bespeakBillRecord.getPort_no()));
			obj.setUserCard(bespeakBillRecord.getUser_pay_card());
			obj.setStartTime(bespeakBillRecord.getStart_time().toString());
			obj.setReservationSn(bespeakBillRecord.getBespeak_jrnl());

			log.info("Send message to reservation Notification" + new Date().getTime());
//			JsonCommon json = systemAppServerRpcClient.reservationNotify(obj);
			json = new JsonCommon<>();
			json.setCode("200");
			log.info("Send message to reservation Notification return" + new Date().getTime());
			if (!json.getCode().equals(AppServerConstant.RELULT_INFO_APP_SERVIER_NOTIFY_SUCCESS_CODE))
				throw new BizException(json.getCode() + ", " + json.getMsg());
		}
		else
		{ // TODO peizhide 预留第三方接口
		}
	}

	private void notifyOnReservationFee(RetVO.CreatedOrderVO retVO, OmsChargerBespeakBillRecord omsChargerBespeakBillRecord) throws BizException
	{
		if (CardUtils.generateCardType(omsChargerBespeakBillRecord.getUser_pay_card()).equals(OmsConstant.CardTypeEnum.OnlineApp))
		{ // APP卡号
			log.info("Receive response message from bespeakReturn(AppReservationNotifyParam)");
			// 通知appServer start 
			AppOrderNotifyParam appOrderNotifyParam= new AppOrderNotifyParam();
			appOrderNotifyParam.setUserCard(omsChargerBespeakBillRecord.getUser_pay_card());
			appOrderNotifyParam.setOrderNo(retVO.getOrderNo());
			appOrderNotifyParam.setMoney(retVO.getTotalFee().toEngineeringString());
			// 取消预约(pojo中组装预约记录表流水号)
			json.setPojo(omsChargerBespeakBillRecord.toString());
//			json = systemAppServerRpcClient.orderNotify(appOrderNotifyParam);
			json = new JsonCommon<>();
			json.setCode("200");
			
			// 通知appServer end
			if (!json.getCode().equals(AppServerConstant.RELULT_INFO_APP_SERVIER_NOTIFY_SUCCESS_CODE))
				throw new BizException(json.getCode() + ", " + json.getMsg());
		}
		else
		{ // TODO peizhide 预留第三方接口
		}
	}

	private RetVO.CreatedOrderVO createOrderWhenCancelReservation(OmsChargerBespeakBillRecord bespeakBillRecord, OmsCharger charger, List<PaymentDetail> reservationFeeDetails) throws BizException
	{
		log.info("Create order via order server");
		List<OrderBaseData> list = new ArrayList<>();
		OrderBaseData orderBaseData = new OrderBaseData();
		orderBaseData.setCardNo(bespeakBillRecord.getUser_pay_card());
		orderBaseData.setCardType(CardUtils.generateCardType(bespeakBillRecord.getUser_pay_card()));
		orderBaseData.setPayerBalance("0");
		orderBaseData.setAppId(BizSystemCode.DzApp.value());
		orderBaseData.setServiceNo(OrderServiceEnum.Reservation.value());
		orderBaseData.setServiceProviderCode(charger.getOper_merchant_id());
		orderBaseData.setPlantId(charger.getStation_id());
		orderBaseData.setEquipmentNo(charger.getCharger_id());
		orderBaseData.setAuxEquipmentNo(bespeakBillRecord.getPort_no().toString());
		orderBaseData.setTotalPrice(new BigDecimal(bespeakBillRecord.getBespeak_deal_before()));
		orderBaseData.setBuyNum(new BigDecimal((bespeakBillRecord.getActual_end_time().getTime() - bespeakBillRecord.getStart_time().getTime()) / (1000 * 60)));
		orderBaseData.setStartTime(bespeakBillRecord.getStart_time());
		orderBaseData.setEndTime(bespeakBillRecord.getActual_end_time());
		orderBaseData.setPayStatus(0);
		orderBaseData.setMessage(JSON.toJSONString(reservationFeeDetails));
		list.add(orderBaseData);

		log.info("Send to  message from ev3c2cancelBespeakReturn orderRpcClient.createOrder! curTime = " + new Date().getTime());
		//RetVO retVO = orderRpcClient.createOrder(list);
		RetVO retVO = null;
		if (retVO == null || !retVO.getRetCode().equals(RetVO.SuccessCode))
			throw new BizException("create order error via order server while cancelling a reservation");

		String bizData = retVO.getBizData().toString();
		log.debug(bizData);
		RetVO.CreatedOrderVO createdOrderVO = JSON.parseObject(bizData, RetVO.CreatedOrderVO.class);
		return createdOrderVO;
	}


}
